﻿using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Utilities;

namespace AiQiuQuan.Sport.Core.WechatPayV3
{
    /// <summary>
    /// 微信支付V3 httpclient
    /// </summary>
    public interface IWechatPayV3HttpClientFactory
    {
        /// <summary>
        /// 微信支付V3 httpclient
        /// </summary>
        /// <param name="merchantId">商户号</param>
        WechatTenpayClient Create(string merchantId = "");
    }

    /// <summary>
    /// 微信支付V3 httpclient
    /// </summary>
    public class WechatPayV3HttpClientFactory : IWechatPayV3HttpClientFactory
    {
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly IOptions<WechatPayOption> _options;
        private readonly IWechatPayV3CertificateManagerFactory _tenpayCertificateManagerFactory;
        private readonly string _certSerialNO;
        private readonly string _certPrivateKeyPem;
        private readonly ILoggerFactory _loggerFactory;

        /// <summary>
        /// ctor
        /// </summary>
        public WechatPayV3HttpClientFactory(
            IOptions<WechatPayOption> options,
            IHttpClientFactory httpClientFactory,
            IWechatPayV3CertificateManagerFactory tenpayCertificateManagerFactory,
            ILoggerFactory loggerFactory)
        {
            _options = options;
            _httpClientFactory = httpClientFactory;
            _tenpayCertificateManagerFactory = tenpayCertificateManagerFactory;
            _certSerialNO = RSAUtility.ExportSerialNumber(GetFileContent(Path.Combine(AppContext.BaseDirectory, _options.Value.CertCer)));
            _certPrivateKeyPem = GetFileContent(Path.Combine(AppContext.BaseDirectory, _options.Value.CertPrivateKeyPem));
            _loggerFactory = loggerFactory;
        }

        /// <summary>
        /// 微信支付V3 httpclient
        /// </summary>
        /// <param name="merchantId">商户号</param>
        public WechatTenpayClient Create(string merchantId = "")
        {
            var wechatTenpayClientOptions = new WechatTenpayClientOptions()
            {
                MerchantId = _options.Value.MchId,
                MerchantV3Secret = _options.Value.APIv3Key,
                MerchantCertificateSerialNumber = _certSerialNO,
                MerchantCertificatePrivateKey = _certPrivateKeyPem,
                PlatformCertificateManager = _tenpayCertificateManagerFactory.Create(_options.Value.MchId),
            };
            var wechatTenpayClient = new WechatTenpayClient(wechatTenpayClientOptions);
            wechatTenpayClient.Interceptors.Add(new FlurlHttpLoggingInterceptor(_loggerFactory.CreateLogger("wechat")));
            wechatTenpayClient.Configure((settings) => settings.FlurlHttpClientFactory = new DelegatingFlurlClientFactory(_httpClientFactory));
            return wechatTenpayClient;

        }

        /// <summary>
        /// DelegatingFlurlClientFactory
        /// </summary>
        internal class DelegatingFlurlClientFactory : Flurl.Http.Configuration.DefaultHttpClientFactory
        {
            private readonly IHttpClientFactory _httpClientFactory;

            /// <summary>
            /// ctor
            /// </summary>
            public DelegatingFlurlClientFactory(IHttpClientFactory httpClientFactory)
            {
                _httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
            }

            /// <summary>
            /// CreateHttpClient
            /// </summary>
            public override HttpClient CreateHttpClient(HttpMessageHandler handler)
            {
                return _httpClientFactory.CreateClient();
            }
        }

        #region private methods
        /// <summary>
        /// 获取文件内容
        /// </summary>
        private string GetFileContent(string filePath)
        {
            if (!File.Exists(filePath))
            {
                return string.Empty;
            }

            using (var reader = new StreamReader(filePath))
            {
                var content = reader.ReadToEnd();
                return content;
            }
        }
        #endregion
    }
}
